// 引用折叠:
//  C++11 之后，引用的引用在特定情况下允许存在，
// 他们会在编译时，被自动化简为左值引用或者右值引用，化简的过程称为 "引用折叠"。
// 化简的规则如下：
// T& &   => T&
// T&& &  => T&
// T& &&  => T&
// T&& && => T&&

#include <iostream>
#include <memory>
#include <utility>

using namespace std;

class CTemp {
 public:
  CTemp() { std::cout << "CTemp()" << std::endl; }
  CTemp(int& x) { std::cout << "CTemp(int&)" << std::endl; }
  CTemp(int&& x) { std::cout << "CTemp(int&&)" << std::endl; }
};

using T = CTemp;

using T1 = T&;
using T2 = T&&;

using T3 = T1 &;  // T& &   => T&
using T4 = T1 &&;  // T& &&  => T&
using T5 = T2 &;   // T&& &  => T&
using T6 = T2 &&;  // T&& &&  => T&&

int main() {
    // 通过编译器编译提示查看类型
    T3 a = nullptr; // error: non-const lvalue reference to type 'T' (aka 'CTemp') cannot bind to a temporary of type 'nullptr_t'
    T4 b = nullptr; // error: non-const lvalue reference to type 'T' (aka 'CTemp') cannot bind to a temporary of type 'nullptr_t'
    T5 c = nullptr; // error: non-const lvalue reference to type 'T' (aka 'CTemp') cannot bind to a temporary of type 'nullptr_t'
    T6 d = nullptr; // error: reference to type 'T' (aka 'CTemp') could not bind to an rvalue of type 'nullptr_t'

    // 由编译错误提示可知，除了 T6 是右值(rvalue)外，其他都是左值(lvalue)

    return 0;
}